package cn.xyt.net;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.tom.mvc.ext.BeanFactory;
import cn.tom.protocol.http.HttpMessage;
import cn.tom.protocol.http.HttpMessageAdaptor;
import cn.tom.transport.Messager.MessageHandler;
import cn.tom.transport.Session;
import cn.tom.transport.nio.NioServer;
import cn.xyt.dto.Form;
import cn.xyt.dto.SystemProperty;
import cn.xyt.service.CmdService;
import cn.xyt.service.RpcService;
import cn.xyt.util.DeviceCache;
import cn.xyt.util.HttpUtil;
import cn.xyt.util.PullSession;
import cn.xyt.util.WebRequestCache;
import io.netty.channel.Channel;
/**
 * 开放内网 rpc 接口调用
 * @author tomsun
 */
@Service
public class RpcController {
	
	@Resource
	CmdService cmdService;
	
	@Resource
	RpcService rpcService;
	
	@Autowired
	private SystemProperty property;
	
	public static Map<Integer, Object[]> cmds = new HashMap<>();

	static{
		try{
			
			cmds.put(0x0E, new Object []{0x8E, CmdService.class.getMethod("cmd_0E", Form.class)}); //机主号码绑定/解绑
			cmds.put(0x0D, new Object []{0x8D, CmdService.class.getMethod("cmd_0D", Form.class)}); //报警号码绑定/解绑
			cmds.put(0x0C, new Object []{0x8C, CmdService.class.getMethod("cmd_0C", Form.class)}); //重启动命令
			cmds.put(0x0B, new Object []{0x8B, CmdService.class.getMethod("cmd_0B", Form.class)} ); //恢复出厂设置命令
			cmds.put(0x0A, new Object []{0x8A, CmdService.class.getMethod("cmd_0A", Form.class)} ); //设置短信报警发送选择命令
			cmds.put(0x10, new Object []{0x90, CmdService.class.getMethod("cmd_10", Form.class)} ); //布防/撤防命令
			cmds.put(0x11, new Object []{0x91, CmdService.class.getMethod("cmd_11", Form.class)} ); //启动/停止命令
			cmds.put(0x12, new Object []{0x92, CmdService.class.getMethod("cmd_12", Form.class)} ); //锁/解 电机命令
			
			cmds.put(0x13, new Object []{0x93, CmdService.class.getMethod("cmd_13", Form.class)} ); //远程断电/远程恢复命令
			cmds.put(0x14, new Object []{0x94, CmdService.class.getMethod("cmd_14", Form.class)} ); //解除报警命令命令
			cmds.put(0x15, new Object []{0x95, CmdService.class.getMethod("cmd_15", Form.class)} ); //静音报警/解除静音报警命令
			cmds.put(0x16, new Object []{0x96, CmdService.class.getMethod("cmd_16", Form.class)} ); //报警灵敏度设置命令
			cmds.put(0x17, new Object []{0x97, CmdService.class.getMethod("cmd_17", Form.class)} ); //寻车信号命令
			cmds.put(0x18, new Object []{0x98, CmdService.class.getMethod("cmd_18", Form.class)} ); //关机命令
			cmds.put(0x19, new Object []{0x99, CmdService.class.getMethod("cmd_19", Form.class)} ); //蓝牙透传命令
			cmds.put(0x1A, new Object []{0x9A, CmdService.class.getMethod("cmd_1A", Form.class)} ); //定时充电命令
			cmds.put(0x1B, new Object []{0x9B, CmdService.class.getMethod("cmd_1B", Form.class)} ); //电瓶电压设定命令
			cmds.put(0x1C, new Object []{0x9C, CmdService.class.getMethod("cmd_1C", Form.class)} ); //时间设定命令
			cmds.put(0x1D, new Object []{0x9D, CmdService.class.getMethod("cmd_1D", Form.class)} ); //蓝牙ID设置
			cmds.put(0x1E, new Object []{0x9E, CmdService.class.getMethod("cmd_1E", Form.class)} ); //蓝牙距离设定命令
			
			cmds.put(0x20, new Object []{0XA0, CmdService.class.getMethod("cmd_20", Form.class)} ); //程序升级准备命令
			cmds.put(0x25, new Object []{0XA5, CmdService.class.getMethod("cmd_25", Form.class)} ); //程序升级确认命令
			
			cmds.put(0x28, new Object []{0XA8, CmdService.class.getMethod("cmd_28", Form.class)} ); //坐垫锁开锁
			cmds.put(0x29, new Object []{0XA9, CmdService.class.getMethod("cmd_29", Form.class)} ); //gps 上传时间设置
			cmds.put(0x2A, new Object []{0XAA, CmdService.class.getMethod("cmd_2A", Form.class)} ); //坐垫锁设置
			cmds.put(0x2B, new Object []{0XAB, CmdService.class.getMethod("cmd_2B", Form.class)} ); //设置涨闸锁参数
			cmds.put(0x2C, new Object []{0XAC, CmdService.class.getMethod("cmd_2C", Form.class)} ); //综合设置命令
			
			// LED 透传命令 
			cmds.put(0x2E, new Object []{0xAE, CmdService.class.getMethod("cmd_2E", Form.class)} );
			cmds.put(0x2F, new Object []{0xAF, CmdService.class.getMethod("cmd_2F", Form.class)} );  // LED 设置 命令
			
			cmds.put(0x30, new Object []{0xB0, CmdService.class.getMethod("cmd_30", Form.class)} );  // 防止扰民参数
			cmds.put(0x31, new Object []{0xB1, CmdService.class.getMethod("cmd_31", Form.class)} );  // 电池类型设置、APP注销命令
			cmds.put(0x32, new Object []{0xB2, CmdService.class.getMethod("cmd_32", Form.class)} );  // 电动车控制器设置命令
			
			// 套套机命令
			cmds.put(0x33, new Object []{0xB3, CmdService.class.getMethod("cmd_33", Form.class)} );  // 电动车控制器设置命令
			// 限速命令
			cmds.put(0x35, new Object []{0xB5, CmdService.class.getMethod("cmd_35", Form.class)} );  
			
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	
	/**
	 * http://127.0.0.1:7070/sendcmd?cmd=11&deviceid=123456&code=2,1
	 * @param res
	 * @param form
	 */
	public void sendCmd(HttpMessage msg, Session sess){
		Form form = new Form();
		form.setCmd(msg.getHeadOrParam("cmds"));
		form.setCode(msg.getHeadOrParam("code"));
		form.setDeviceid(msg.getHeadOrParam("deviceid"));
		String cmd = form.getCmd();
		int _cmd = Integer.parseInt(cmd, 16);
		Object [] obj = cmds.get(_cmd);
		/*返回命令msgid*/
		int resp_msgid = (int) obj[0] ; 
		form.setResp_cmd(Integer.toHexString(resp_msgid));
		/*发送消息方法调用*/
		Method me = (Method) obj[1];
		try {
			Object res = me.invoke(cmdService, form);  
			msg.setJsonBody(HttpUtil.serialize(res));
			msg.setStatus("200");  
			sess.write(msg);
		} catch (Exception e) {
			cmdService.logger.error(e.getMessage(), e);
		}
	}
	
	/**
	 * 异步发送
	 * @param msg
	 * @param sess
	 */
	public void sendCmdAsync(HttpMessage msg, Session sess){
		Form form = new Form();
		form.setCmd(msg.getHeadOrParam("cmds"));
		form.setCode(msg.getHeadOrParam("code"));
		form.setDeviceid(msg.getHeadOrParam("deviceid"));
		String cmd = form.getCmd();
		int _cmd = Integer.parseInt(cmd, 16);
		Object [] obj = cmds.get(_cmd);
		/*返回命令msgid*/
		int resp_msgid = (int) obj[0] ; 
		form.setResp_cmd(Integer.toHexString(resp_msgid));
		/*发送消息方法调用*/
		Method me = (Method) obj[1];
		try{
			Map<String, Object> resp =(Map<String, Object>) me.invoke(cmdService, form);  //TODO  改成异步的
			if("001".equals(resp.get("state"))){
				msg.setJsonBody(HttpUtil.serialize(resp));
				msg.setStatus("200");  
				sess.write(msg);
				return;
			}
			WebRequestCache.set((String)resp.get("data"), new PullSession(sess, msg));
		}catch(Exception e){
			cmdService.logger.error(e.getMessage(), e);
		}
	}

	
	public void get(HttpMessage msg, Session sess){ 
		long a  = System.currentTimeMillis();
		String module = msg.getMeta().getParam("module");
		HttpMessage res = rpcService.invoke(msg, sess);
		if(res == null) return;
		rpcService.logger.info("rpcService.module:"+ module +" last: "+ (System.currentTimeMillis()-a));
		sess.write(res);
	}
	
	public void post(HttpMessage msg, Session sess){ 
		long a  = System.currentTimeMillis();
		String module = msg.getMeta().getParam("module");
		HttpMessage res = rpcService.invoke(msg, sess);
		if(res == null) return;
		rpcService.logger.info("rpcService.module:"+ module +" last: "+ (System.currentTimeMillis()-a));
		sess.write(res);
	}
	
	
	/**
	 *  NIO rpc Server
	 * @throws IOException
	 */
	@PostConstruct
	public void startServer() throws IOException{
		NioServer server = new NioServer("0.0.0.0", property.getHttpMsgPort());
		HttpMessageAdaptor adaptorServer = new HttpMessageAdaptor();
		BeanFactory.singletons.put("adaptorServer", adaptorServer);
		adaptorServer.registerHandler("get", new MessageHandler<HttpMessage>() {
			@Override
			public void handleMessage(HttpMessage msg, Session sess) throws IOException {
				get(msg, sess);
			}

		});
		
		adaptorServer.registerHandler("sendcmd", new MessageHandler<HttpMessage>() {
			@Override
			public void handleMessage(HttpMessage msg, Session sess) throws IOException {
				sendCmdAsync(msg, sess);
			}
		});
		
		server.setIoAdaptor(adaptorServer);
		server.start();
	}
	
	

}
